TITL DAI FIRMWARE C7FB-CA00 V1.1 ORG :C7FB * * * ********************************* * CHECK FOR HIGHEST RAM ADDRESS * ********************************* * * Entry: No conditions. * Exit: HL points after RAM. * BC preserved, ADEF corrupted. * MEMCHK LXI D,:1000 LXI H,:0000 Start at 0000 MCK10 DAD D Incr. with #1000 MOV A,M Get what is in memory CMA Take its complement MOV M,A and store it back CMP M Then compare CMA MOV M,A Restore original value JZ :C801 Next block if still RAM RET * ********************** * START FROM SCRATCH * ********************** * * Entry to Basic monitor. * REM * If out of a Hard BREAK: REM RSTART LXI SP,:F900 Reset stackpointer CALL :CEE4 Select ROM bank 0, DBL :DBB8 print '*** BREAK' REM * Re-enter Basic after run-time error, * except on input: REM START XRA A STA :0135 Input from keyb/DINC REM * Entry on reset, after encoding program line, * after END: REM ST10 LXI H,:F900 SHLD :0127 Reset current base stack SPHL Reset stackpointer XRA A STA :0126 No suspended program REM * Restart interpreter; entry after end of program, * after direct command, after soft BREAK, after * direct command error, after STOP: REM ST20 LHLD :0127 Get saved stackpointer SPHL Set it to saved value * * * ********************** * START FROM SCRATCH * ********************** * * Added is the reset of all keyboard pointers at * various moments: * - When restarting the Basic interpreter. * - After command execution. Then also the output * direction is reset to screen (to avoid a not * useable keyboard). * - Idem before executing 'break'. * Resetting the keyboard pointers clears the key * input buffer in order to avoid keybounce. * CALL :D563 ] Keyb. pntrs to default LXI H,:0000 SHLD :0100 SHLD :0104 SHLD :0113 MOV A,H STA :0122 * LXI H,:0117 MOV M,A No running of inputs INX H MOV M,A No running of program CALL :D988 Enable keyboard interrupt CALL :D9DB Enable clock interrupt ST23 LDA :0135 Get input direction CPI :02 CZ :D879 EFSW=2: input from editbuf JNC :C867 encode text line if edit MVI A,:2A buffer not empty CALL :DD1A Print '*', scan keyboard REM and display characters REM until Break or car.ret REM (If no input is given, REM the DAI remains here in a REM endless loop). JC :C846 If BREAK: new inputs CALL :DDD2 Get char from line, neglect REM TAB and space CPI :0D JZ :C846 If car.ret: new inputs CALL :DE0D Check if char is number JNC :C86D If no leading nr: encode cmd REM * Encode program line (if 1st char is number): REM ST24 CALL :C918 Encode program line, update REM program JMP :C818 Get next input line; kill REM any suspended program REM * Encode direct command (if 1st char is no number): REM ST25 MVI D,:80 Mask for direct command PUSH H Pointer to RUNF LXI H,:013F Addr EBUF PUSH H Save it on stack RST 1 Encode immediate cmd line DATA :00 MVI M,:00 Dummy end of program CALL :DD5E Print car.ret POP B Get EBUF pntr POP H Pntr to RUNF MVI M,:FF Set flag running programs REM * Run a Basic line: REM ST30 LDAX B Get 1st byte from EBUF: REM < #80: length, REM >= #80: Token. ST35 INX B ADD A Calc offset from CF00 JNC :C8E5 Jump if length byte MOV L,A Get table address in HL MVI H,:CF MOV A,M ) Get addr Basic routine INX H ) from table in HL MOV H,M ) MOV L,A ) CALL :C8A9 Perform this routine REM * Commands return here: REM ENDCOM JC :C8AA Jump if special action REM * If suspended: REM MOV H,B MOV L,C SHLD :0102 Remember start next cmd LXI H,:02C4 ] MOV A,M ] Get break flag ORA A JZ :C87F CALL :D563 ] Keyb.pntrs to default XRA A ] STA :0131 ] Output to screen JMP :C8C0 Handle break REM * Run a BASIC line: REM DCALL PCHL Addr Basic routine in PC REM * If special end of action: REM ST40 CPI :02 * JZ :C89F ] Keyb.pntrs to default, REM output to screen JNC :C8B8 If STOP (3) JPE :C818 If can't continu (1) JMP :C908 If after LOAD (0) REM * If 'STOP': REM ST45 MOV H,B MOV L,C SHLD :0102 Remember where next cmd JMP :C8C5 Print 'IN LINE ..' and REM handle a break REM * If suspended (soft Break handling): REM ST50 CALL :DAFF Print car.ret; 'BREAK'. DBL :DBC5 ST55 CALL :DA75 Print 'IN LINE .....' REM or car.ret JZ :C823 Jump if immediate cmd REM * Only if 'break' in program: REM LXI H,:FFEB Frame length DAD SP New stack level MOV B,H MOV C,L SHLD :0127 Set new base stack SPHL Set stackpointer LXI D,:0100 ) Boundaries frame LXI H,:0115 ) CALL :DE4F Save program status REM (FRAME) on stack. LXI H,:0126 INR M Set flag existence saved REM program JMP :C823 Run again REM * Length byte or end flag: REM ST60 JZ :C823 If end immediate cmd REM line or end program MOV H,B MOV L,C SHLD :0100 Store start current line LHLD :0115 Get trace + step flag MOV A,H ORA L JZ :C900 If no step/trace flag REM * If step/trace flag set: REM PUSH H PUSH B CALL :CEA4 List current line POP B POP PSW Get step flag ORA A If set: CNZ :D6DA Wait for spacebar pressed ST65 INX B INX B Pnts after linenr JC :C8CB If Break JMP :C87F Run next BASIC line REM * Special action after LOAD: REM ST70 LHLD :0100 Get start current line MOV A,H ORA L Direct cmd? JZ :C87F Then run Basic line LXI SP,:F900 Else: reset stackpointer MVI A,:87 Simulate Token 'RUN' JMP :C880 Pretend RUN cmd * * PROGRAM INPUT: * * Encodes a program line and updates the stored * program. * * Entry: C: Input count / offset. * Exit: C: Offset after line. * AFBDEHL preserved. * PROGI LXI H,:013F Addr buf for encoded cmds RST 1 Get linenr DATA :03 CALL :DDD2 Get char from line; REM neglect TAB + space CPI :0D Car.ret ? CZ :C9A2 Delete old version if REM only linenr given JZ :C93B Jump if linenr only PUSH D Remember linenr MVI D,:40 Mask for 'stored cmd' CALL :C93C Encode a line MOV A,L SUI :3F Length string in A STA :013E Length in EBUF POP D Get linenr CALL :C9A2 Delete old line CALL :C9BD Insert new line PGI20 RET * * ENCODE A LINE: * * Exit: DE restored. * HL points to 1st free byte in EBUF. * C points after car.ret in input. * A=0, F corrupted. * ELINA PUSH D PUSH B PUSH H LXI H,:0000 DAD SP Stackpointer in HL SHLD :011D Save stackpointer POP H PUSH H MVI A,:01 STA :0122 Set encoding a stored line RST 1 Encode inputs DATA :00 POP D ) Cancel Push B,H POP D ) ELA10 XRA A STA :0122 No encoding stored line POP D RET * ************************************** * ERROR WHILE ENCODING A STORED LINE * ************************************** * * Restores stackpointer, adds '***' to begin of * line, adds '?' to place of error. Line is entered * into the encoded inputbuffer (EBUF). * * Entry: B: Errorcode. * C: Place of error. * On stack: BC points to input. * HL points to EBUF. * ELARS LHLD :011D Get ERSSP SPHL Restore stackpointer POP H Get buffer pointer MOV A,B Errorcode in A MOV D,C Place of error in D POP B Get input pointer MOV B,A MVI M,:B1 Token for '***' in EBUF INX H PUSH H Save buf pointer INX H ELA20 MOV A,C ) Place of error CMP D ) reached ? MVI A,:3F CZ :C995 Then insert '?' CALL :DDE0 Get char. from line INR C Update inputpointer CPI :0D Line done ? CNZ :C995 Insert char in EBUF if not JNZ :C965 Next char if not ready MOV A,L Lobyte EBUF pntr in A POP D Addr after '***' SUB E DCR A STAX D Store length in EBUF MVI M,:00 0 after string PUSH B Save errormessage pntr MOV B,D ) EBUF pntr in BC MOV C,E ) DCX B DCX B DCX B DCX B Pnts to begin EBUF CALL :DD5E Print car.ret CALL :ECAB (0) List current line POP B Get errormessage pntr PUSH H CALL :DA50 Print errormessage POP H JMP :C951 Store 0 in ERSFL, Pop D, REM and ret. * * INSERT CHARACTER IN ENCODED INPUT BUFFER: * * A character is inserted in the EBUF only if * there is space available. * * Entry: HL: 1st free location in EBUF. * A: Character to be inserted. * Exit: HL updated. AFBCDE preserved. * ELAIN PUSH PSW MOV A,L Get lobyte of EBUF pntr CPI :BC Buffer full ? JZ :C9A0 Then abort POP PSW MOV M,A Char into EBUF INX H Update pntr RET REM * If EBUF full: REM EAI10 POP PSW No action RET * ******************************** * DELETE OLD VERSION OF A LINE * ******************************** * * A textline is deleted by moving the rest of the * textbuffer and the symboltable 'downwards'. * * Entry: DE: requested linenumber. * Exit: DE points to linenr after deleted line. * AFBCHL preserved. * LDEL PUSH PSW PUSH B PUSH H XCHG Linenr in HL CALL :CAF6 Addr line in textbuf in HL JNC :C9B8 Abort if not found MOV A,M Get line length CMA MOV E,A Compl. value in E MVI D,:FF CALL :DE39 HL=HL-line length XCHG CALL :C9D1 Move program buffers LDL10 XCHG POP H POP B POP PSW RET * ********************* * INSERT A NEW LINE * ********************* * * Inserts a encoded line in the textbuffer. * Required space for the textline is made by * shifting the rest of the textbuffer and the * symboltable 'upwards'. * * Entry: DE: Destination address in textbuffer. * HL: Points after string in EBUF. * A: Length string in EBUF. * LINS PUSH B PUSH H MOV L,A MVI H,:00 String length in HL INX H Required space in HEAP PUSH D CALL :C9D1 Move program buffers POP B POP H LXI D,:013E Startaddr. EBUF CALL :DE4F Transfer data from EBUF REM into textbuffer POP B RET * ************************ * MOVE PROGRAM BUFFERS * ************************ * * Moves a part (or the whole) textbuffer and the * whole symboltable up or down. * The startaddress of the textbuffer and the end * of the symboltable are set depending on the * heap size. The heap pointers are updated. * * Entry: DE: Address from where to update. * HL: Length of area to be inserted/deleted. * Entry if running 'NEW' only: * BC: 0. * DE: startaddress Heap. * HL: Size Heap. * At entry, the pointers for textbuf and * symtab are as if HEAPsize is zero. * Exit: AFBCDE preserved. * HL: New startaddress. * PROGM PUSH B PUSH D MOV B,D ) Addr from where to MOV C,E ) update in BC XCHG Length area in DE LHLD :02A3 Get end symtab PUSH H PUSH D DAD D New end symtab XCHG LHLD :02A5 Get bottom screen RAM CALL :DE14 Check for overflow XCHG End symtab in HL JC :DA10 Evt. run 'OUT OF MEMORY' SHLD :02A3 Store end symbol table POP D PUSH D LHLD :02A1 Get begin symtab DAD D New begin symtab SHLD :02A1 Store begin symbol table PRGM1 POP H MOV D,B MOV E,C Startaddr in DE DAD D New startaddr MOV B,H MOV C,L New startaddr in BC XTHL Get old end symtab CALL :DE4F Move textbuf + symtab REM from old to new addr. POP H POP D POP B RET * * * END